package ${sysTableVo.packageName}.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.ListUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.github.yulichang.wrapper.MPJLambdaWrapper;
import com.jichangxiu.common.annotation.Source;
import com.jichangxiu.common.entity.bo.ValidateBos;
import com.jichangxiu.common.exception.ServiceException;
import com.jichangxiu.common.utils.ConvertUtils;
import com.jichangxiu.framework.service.impl.BaseServiceImpl;
import com.jichangxiu.framework.utils.ValidateUtils;
import ${sysTableVo.packageName}.entity.bo.${sysTableVo.bigClassName}Bo;
import ${sysTableVo.packageName}.entity.dto.add.Add${sysTableVo.bigClassName};
import ${sysTableVo.packageName}.entity.dto.edit.Edit${sysTableVo.bigClassName};
import ${sysTableVo.packageName}.entity.dto.query.Query${sysTableVo.bigClassName};
import ${sysTableVo.packageName}.entity.po.${sysTableVo.bigClassName};
import ${sysTableVo.packageName}.entity.vo.${sysTableVo.bigClassName}Vo;
import ${sysTableVo.packageName}.mapper.${sysTableVo.bigClassName}Mapper;
import ${sysTableVo.packageName}.service.${sysTableVo.bigClassName}Service;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.validation.constraints.NotBlank;
import java.util.List;
import java.util.stream.Collectors;
import java.util.stream.Stream;

/**
 * ${sysTableVo.bigClassName}ServiceImpl:
 *
 * @author ${sysTableVo.functionAuthor}
 * @create ${datetime}
 */
@Service
public class ${sysTableVo.bigClassName}ServiceImpl extends BaseServiceImpl<${sysTableVo.bigClassName}Mapper, ${sysTableVo.bigClassName}, ${sysTableVo.bigClassName}Vo> implements ${sysTableVo.bigClassName}Service {

    #if($sysTableVo.subTableId)
    @Resource
    private ${subSysTableVo.bigClassName}Service ${subSysTableVo.className}Service;

    #end
    /**
     * 新增${sysTableVo.functionName}
     *
     * @param add${sysTableVo.bigClassName} 新增${sysTableVo.functionName}视图对象
     * @return 是否成功
     */
    @Source
    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean add(Add${sysTableVo.bigClassName} add${sysTableVo.bigClassName})  {
        return getBaseMapper().insert(addAndEditValidBo(ConvertUtils.convert(add${sysTableVo.bigClassName}, ${sysTableVo.bigClassName}Bo.class))) > 0;
    }

    /**
     * 单（多）选删除${sysTableVo.functionName}
     *
     * @param idList ${sysTableVo.functionName}主键列表
     * @return 是否成功
     */
    @Source
    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean del(List<String> idList) {
        return getBaseMapper().deleteBatchIds(delValid(idList)) > 0;
    }

    /**
     * 修改${sysTableVo.functionName}
     *
     * @param edit${sysTableVo.bigClassName} 修改${sysTableVo.functionName}视图对象
     * @return 是否成功
     */
    @Source
    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean edit(Edit${sysTableVo.bigClassName} edit${sysTableVo.bigClassName}) {
        return getBaseMapper().updateById(addAndEditValidBo(ConvertUtils.convert(edit${sysTableVo.bigClassName}, ${sysTableVo.bigClassName}Bo.class))) > 0;
    }

    /**
     * 根据主键查询${sysTableVo.functionName}
     *
     * @param id ${sysTableVo.functionName}主键
     * @param isExtend 是否扩展
     * @return ${sysTableVo.functionName}详情
     */
    @Source
    @Override
    public ${sysTableVo.bigClassName}Vo info(@NotBlank(message = "主键不能为空") String id, Boolean isExtend) {
        ${sysTableVo.bigClassName}Vo ${sysTableVo.className}Vo = getBaseMapper().selectJoinOne(${sysTableVo.bigClassName}Vo.class, buildQueryWrapper(Query${sysTableVo.bigClassName}.builder().${primarySysColumnVu.javaField}(id).build()));
        if (Boolean.TRUE.equals(isExtend)) {
            if (ObjectUtil.isNotEmpty(${sysTableVo.className}Vo)) {
                ${sysTableVo.className}Vo = render${sysTableVo.bigClassName}VoList(ListUtil.toList(${sysTableVo.className}Vo)).get(0);
            }
        }
        return ${sysTableVo.className}Vo;
    }

    /**
     * （可分页）查询${sysTableVo.functionName}列表
     *
     * @param query${sysTableVo.bigClassName} 查询视图对象
     * @return （分页）${sysTableVo.functionName}列表
     */
    @Source
    @Override
    public Page<${sysTableVo.bigClassName}Vo> lists(Query${sysTableVo.bigClassName} query${sysTableVo.bigClassName}) {
        Page<${sysTableVo.bigClassName}Vo> ${sysTableVo.className}VoPage = getBaseMapper().selectJoinPage(startPage(), ${sysTableVo.bigClassName}Vo.class, buildQueryWrapper(query${sysTableVo.bigClassName}));
        if (Boolean.TRUE.equals(query${sysTableVo.bigClassName}.getIsExtend())) {
            ${sysTableVo.className}VoPage.setRecords(render${sysTableVo.bigClassName}VoList(${sysTableVo.className}VoPage.getRecords()));
        }
        return ${sysTableVo.className}VoPage;
    }

    /**
     * 新增 / 修改 前校验
     *
     * @param ${sysTableVo.className}Bo 校验用业务对象
     * @return 数据库操作对象
     */
    public ${sysTableVo.bigClassName} addAndEditValidBo(${sysTableVo.bigClassName}Bo ${sysTableVo.className}Bo) {
        ${sysTableVo.bigClassName} ${sysTableVo.className} = ConvertUtils.convert(${sysTableVo.className}Bo, ${sysTableVo.bigClassName}.class);
        if (ObjectUtil.isEmpty(${sysTableVo.className})) {
            throw new ServiceException("待校验对象为空");
        }
#if($uniqueCount > 0)
        List<ValidateBos> validateBosList = Stream.of(
    #if($primarySysColumnVu)
            ValidateUtils.createNeValidateBos(ValidateUtils.createValidateBo(${sysTableVo.bigClassName}::get${primarySysColumnVu.bigJavaField}, ${sysTableVo.className}.get${primarySysColumnVu.bigJavaField}(), "主键")),
    #end
    #if($uniqueCount > 0)
            ValidateUtils.createOrEqValidateBos(
        #set($index = 1)
        #foreach ($sysColumnVo in $sysColumnVoList)
            #if($sysColumnVo.isQuery && $sysColumnVo.isUnique && !$sysColumnVo.isPrimaryKey)
                #set($index = $index + 1)
                ValidateUtils.createValidateBo(${sysTableVo.bigClassName}::get${sysColumnVo.bigJavaField}, ${sysTableVo.className}.get${sysColumnVo.bigJavaField}(), "${sysColumnVo.comment}")#if($index != $uniqueCount),#else)#end
            #end
        #end
    #end
        ).collect(Collectors.toList());
        // 唯一校验
        ValidateUtils.uniqueValidate(this::countWrapper, validateBosList);
#end
        if (StrUtil.isEmpty(${sysTableVo.className}.get${primarySysColumnVu.bigJavaField}())) {
            // 新增
            return ${sysTableVo.className};
        } else {
            // 修改
            ${sysTableVo.bigClassName} db${sysTableVo.bigClassName} = getById(${sysTableVo.className}.get${primarySysColumnVu.bigJavaField}());
            BeanUtil.copyProperties(${sysTableVo.className}, db${sysTableVo.bigClassName}, true);
            return db${sysTableVo.bigClassName};
        }
    }

    /**
     * 删除前校验
     *
     * @param idList 主键列表
     * @return 主键列表
     */
    public List<String> delValid(List<String> idList) {
        if (ObjectUtil.isEmpty(idList)) {
            throw new ServiceException("待校验主键列表为空");
        }
#if($sysTableVo.subTableId)
        if (${subSysTableVo.className}Service.count(new LambdaQueryWrapper<${subSysTableVo.bigClassName}>().in(${subSysTableVo.bigClassName}::get${subSysColumnVo.bigJavaField}, idList)) != 0) {
            throw new ServiceException("主表下尚有详情，不能删除");
        }
#end
        return idList;
    }

    /**
     * 渲染视图
     *
     * @param ${sysTableVo.className}VoList 视图列表
     * @return 渲染后的视图列表
     */
    public List<${sysTableVo.bigClassName}Vo> render${sysTableVo.bigClassName}VoList(List<${sysTableVo.bigClassName}Vo> ${sysTableVo.className}VoList) {
        if (ObjectUtil.isEmpty(${sysTableVo.className}VoList)) {
            // todo 扩展信息填入
#if($sysTableVo.subTableId)
            List<${subSysTableVo.bigClassName}Vo> ${subSysTableVo.className}VoList = ${subSysTableVo.className}Service.voList(new LambdaQueryWrapper<${subSysTableVo.bigClassName}>().in(${subSysTableVo.bigClassName}::get${subSysColumnVo.bigJavaField}, ${sysTableVo.className}VoList.stream().map(${sysTableVo.bigClassName}Vo::get${primarySysColumnVu.bigJavaField}).collect(Collectors.toList())));
            if (ObjectUtil.isNotEmpty(${subSysTableVo.className}VoList)) {
                Map<String, List<${subSysTableVo.bigClassName}Vo>> map = ${subSysTableVo.className}VoList.stream().collect(Collectors.groupingBy(${subSysTableVo.bigClassName}Vo::get${subSysColumnVo.bigJavaField}, Collectors.toList()));
                ${sysTableVo.className}VoList.forEach(${sysTableVo.className}Vo -> ${sysTableVo.className}Vo.set${subSysTableVo.bigClassName}VoList(map.get(${sysTableVo.className}Vo.get${primarySysColumnVu.bigJavaField}())));
            }
#end
        }
        return ${sysTableVo.className}VoList;
    }

    /**
     * 构建查询条件
     *
     * @param query${sysTableVo.bigClassName} 查询用业务对象
     * @return 查询条件
     */
    public MPJLambdaWrapper<${sysTableVo.bigClassName}> buildQueryWrapper(Query${sysTableVo.bigClassName} query${sysTableVo.bigClassName}) {
        MPJLambdaWrapper<${sysTableVo.bigClassName}> lambdaQueryWrapper = new MPJLambdaWrapper<${sysTableVo.bigClassName}>().selectAll(${sysTableVo.bigClassName}.class);
#foreach ($sysColumnVo in $sysColumnVoList)
    #if($sysColumnVo.isQuery)
        #if($sysColumnVo.queryType == "EQ")
            #if($sysColumnVo.javaType == "String")
        lambdaQueryWrapper.eq(StrUtil.isNotEmpty(query${sysTableVo.bigClassName}.get${sysColumnVo.bigJavaField}()), ${sysTableVo.bigClassName}::get${sysColumnVo.bigJavaField}, query${sysTableVo.bigClassName}.get${sysColumnVo.bigJavaField}());
            #else
        lambdaQueryWrapper.eq(ObjectUtil.isNotEmpty(query${sysTableVo.bigClassName}.get${sysColumnVo.bigJavaField}()), ${sysTableVo.bigClassName}::get${sysColumnVo.bigJavaField}, query${sysTableVo.bigClassName}.get${sysColumnVo.bigJavaField}());
            #end
        #elseif($sysColumnVo.queryType == "NE")
            #if($sysColumnVo.javaType == "String")
        lambdaQueryWrapper.ne(StrUtil.isNotEmpty(query${sysTableVo.bigClassName}.get${sysColumnVo.bigJavaField}()), ${sysTableVo.bigClassName}::get${sysColumnVo.bigJavaField}, query${sysTableVo.bigClassName}.get${sysColumnVo.bigJavaField}());
            #else
        lambdaQueryWrapper.ne(ObjectUtil.isNotEmpty(query${sysTableVo.bigClassName}.get${sysColumnVo.bigJavaField}()), ${sysTableVo.bigClassName}::get${sysColumnVo.bigJavaField}, query${sysTableVo.bigClassName}.get${sysColumnVo.bigJavaField}());
            #end
        #elseif($sysColumnVo.queryType == "GT")
            #if($sysColumnVo.javaType == "String")
        lambdaQueryWrapper.gt(StrUtil.isNotEmpty(query${sysTableVo.bigClassName}.get${sysColumnVo.bigJavaField}()), ${sysTableVo.bigClassName}::get${sysColumnVo.bigJavaField}, query${sysTableVo.bigClassName}.get${sysColumnVo.bigJavaField}());
            #else
        lambdaQueryWrapper.gt(ObjectUtil.isNotEmpty(query${sysTableVo.bigClassName}.get${sysColumnVo.bigJavaField}()), ${sysTableVo.bigClassName}::get${sysColumnVo.bigJavaField}, query${sysTableVo.bigClassName}.get${sysColumnVo.bigJavaField}());
            #end
        #elseif($sysColumnVo.queryType == "GTE")
            #if($sysColumnVo.javaType == "String")
        lambdaQueryWrapper.ge(StrUtil.isNotEmpty(query${sysTableVo.bigClassName}.get${sysColumnVo.bigJavaField}()), ${sysTableVo.bigClassName}::get${sysColumnVo.bigJavaField}, query${sysTableVo.bigClassName}.get${sysColumnVo.bigJavaField}());
            #else
        lambdaQueryWrapper.ge(ObjectUtil.isNotEmpty(query${sysTableVo.bigClassName}.get${sysColumnVo.bigJavaField}()), ${sysTableVo.bigClassName}::get${sysColumnVo.bigJavaField}, query${sysTableVo.bigClassName}.get${sysColumnVo.bigJavaField}());
            #end
        #elseif($sysColumnVo.queryType == "LT")
            #if($sysColumnVo.javaType == "String")
        lambdaQueryWrapper.lt(StrUtil.isNotEmpty(query${sysTableVo.bigClassName}.get${sysColumnVo.bigJavaField}()), ${sysTableVo.bigClassName}::get${sysColumnVo.bigJavaField}, query${sysTableVo.bigClassName}.get${sysColumnVo.bigJavaField}());
            #else
        lambdaQueryWrapper.lt(ObjectUtil.isNotEmpty(query${sysTableVo.bigClassName}.get${sysColumnVo.bigJavaField}()), ${sysTableVo.bigClassName}::get${sysColumnVo.bigJavaField}, query${sysTableVo.bigClassName}.get${sysColumnVo.bigJavaField}());
            #end
        #elseif($sysColumnVo.queryType == "LTE")
            #if($sysColumnVo.javaType == "String")
        lambdaQueryWrapper.le(StrUtil.isNotEmpty(query${sysTableVo.bigClassName}.get${sysColumnVo.bigJavaField}()), ${sysTableVo.bigClassName}::get${sysColumnVo.bigJavaField}, query${sysTableVo.bigClassName}.get${sysColumnVo.bigJavaField}());
            #else
        lambdaQueryWrapper.le(ObjectUtil.isNotEmpty(query${sysTableVo.bigClassName}.get${sysColumnVo.bigJavaField}()), ${sysTableVo.bigClassName}::get${sysColumnVo.bigJavaField}, query${sysTableVo.bigClassName}.get${sysColumnVo.bigJavaField}());
            #end
        #elseif($sysColumnVo.queryType == "LIKE")
            #if($sysColumnVo.javaType == "String")
        lambdaQueryWrapper.like(StrUtil.isNotEmpty(query${sysTableVo.bigClassName}.get${sysColumnVo.bigJavaField}()), ${sysTableVo.bigClassName}::get${sysColumnVo.bigJavaField}, query${sysTableVo.bigClassName}.get${sysColumnVo.bigJavaField}());
            #else
        lambdaQueryWrapper.like(ObjectUtil.isNotEmpty(query${sysTableVo.bigClassName}.get${sysColumnVo.bigJavaField}()), ${sysTableVo.bigClassName}::get${sysColumnVo.bigJavaField}, query${sysTableVo.bigClassName}.get${sysColumnVo.bigJavaField}());
            #end
        #else
        lambdaQueryWrapper.eq(ObjectUtil.isNotEmpty(query${sysTableVo.bigClassName}.get${sysColumnVo.bigJavaField}()), ${sysTableVo.bigClassName}::get${sysColumnVo.bigJavaField}, query${sysTableVo.bigClassName}.get${sysColumnVo.bigJavaField}());
        #end
    #end
#end
        return lambdaQueryWrapper;
    }

}